/**************************************************************
 * File Name: server.c
 * User 	: 干部小徐
 * QQ         : 10086
 * Email      : 90090
 * CTime    : 2022年01月19日 星期三 11时50分56秒
***************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>  
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <unistd.h>
#include <assert.h>

/********************************************
 *函数名：server_init
 * 
 *功能：初始化服务器
 *
 * 参数：
 *
 * 返回值：套接字
 *
 **********************************************/
int x_server_init()
{
    //创建套接字
    int x_sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(-1 == x_sockfd)
    {
        perror("socket");
        exit(-1);
    }
    printf("socket ok\n");
    //设置套接字重用
    int x_one = 1;//设置优先级为1
    if(setsockopt(x_sockfd,SOL_SOCKET,SO_REUSEADDR,&x_one,sizeof(x_one))<0)
    {
        perror("setsockopt");
        exit(-1);
    }
    //绑定IP和端口
    struct sockaddr_in x_saddr;
    memset(&x_saddr,0,sizeof(x_saddr));

    x_saddr.sin_family = AF_INET;
    x_saddr.sin_port = htons(8888);
    //x_saddr.sin_addr.s_addr = inet_addr("192.168.22.26");
    x_saddr.sin_addr.s_addr = INADDR_ANY;

    int x_len = sizeof(x_saddr);
    int x_ret = bind(x_sockfd,(struct sockaddr *)&x_saddr,x_len);
    if(x_ret < 0)
    {
        perror("bind");
        exit(-1);
    }
    printf("bind ok\n");

    //设置监听
    if(listen(x_sockfd,5) < 0)
    {
        perror("listen");
        exit(-1);
    }
    printf("等待客户端连接-------\n");
    return x_sockfd;
}

/*******************************************
 *函数名：x_server_wait_connect
 *
 *功能：等待客户端连接
 *
 *参数：x_sockfd
 *
 *返回值：通信套接字
 * *****************************************/
int x_server_wait_connect(int x_sockfd)
{
    struct sockaddr_in x_raddr;
    socklen_t x_addrlen = sizeof(x_raddr);
    int x_connfd = accept(x_sockfd,(struct sockaddr *)&x_raddr,&x_addrlen);
    if(x_connfd < 0)
    {
        perror("accept");
        exit(-1);
    }
    printf("客户端连接成功！\n");
    return x_connfd;
}

/**********************************
 *函数名：x_recv
 *
 *功能：接收客户端发送的数据
 *
 *参数：通信套接字x_connfd,
 *      缓冲区x_buf,
 *      一次读取的字节数x_count
 *
 *返回值：接收的字节数
 *
 * **********************************/
int x_recv(int x_connfd,void *x_buf,int x_count)
{
    int x_ret;

	assert(x_buf != NULL);

	x_ret = read(x_connfd, x_buf, x_count);
	if (x_ret == -1) 
    {
		perror("server->read");
		return -1;
	} 
    else if (x_ret == 0) 
    {
		fprintf(stderr, "server->read: end-of-file\n");
		return 0;
	} 
    else
		return x_ret;
}

/**********************************
 *函数名：x_send()
 *
 *功能：发送数据给客户端
 *
 *参数：通信套接字x_connfd,
 *      缓冲区x_buf,
 *      一次发送的字节数
 *
 * 返回值：发送的字节数
 *
 * **********************************/
int x_send(int x_connfd,void *x_buf,int x_count)
{
    int x_ret;

	assert(x_buf != NULL);

	x_ret = write(x_connfd, x_buf, x_count);
	if (x_ret == -1) 
    {
		perror("server->write");
		return -1;
	} 
    else
		return x_ret;
}

/***********************************
 *函数名：x_recv_nbytes
 *
 *功能：按字节接收数据
 *
 *参数：通信套接字x_connfd，
 *      缓冲区：x_buf，
 *      一次接收的字节数x_count
 *
 *返回值：总共接收的字节数
 * *****************************************/
int x_recv_nbytes(int x_connfd,void *x_buf, int x_count)
{
    int x_ret;
    int x_total = 0;
    assert(x_buf != NULL);

    while (x_total != x_count) 
    {
        x_ret = read(x_connfd, x_buf + x_total, x_count - x_total);
        if (x_ret == -1) 
        {
            perror("server->read");
            sleep(2);
            break;
        } 
        else if (x_ret == 0) 
        {
            fprintf(stderr, "server->read: end-of-file\n");
            return x_total;
        } 
        else
            x_total += x_ret;
    }

    return x_total;
}

/*************************************
 *函数名：x_send_nbytes
 *
 *功能：按字节发送数据
 *
 *参数：通信套接字：x_connfd,
 *      缓冲区：x_buf,
 *      一次发送的字节数：x_count
 *
 *返回值：总共发送的字节数
 * ***************************************/
int x_send_nbytes(int x_connfd,void *x_buf,int x_count)
{
    int x_ret;
	int x_total = 0;

	assert(x_buf != NULL);

	while (x_total != x_count) 
    {
		x_ret = write(x_connfd, x_buf + x_total, x_count - x_total);
		if (x_ret == -1) 
        {
			perror("server->write");
			return x_total;
		} else
			x_total += x_ret;
	}

	return x_total;
}

/*********************************
 *函数名：server_disconnect
 *
 *功能：断开连接
 *
 *参数：通信套接字：x_connfd
 *
 *返回值：成功返回0，失败返回-1
 * ********************************/
int server_disconnect(int x_connfd)
{
    if (close(x_connfd)) 
    {
        perror("server->close");
        return -1;
    }

    return 0;
}
